home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / NDK / NDK_3.5 / Examples / Printer / HP_DeskJet_CMYK / compression.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-10-30  |  5.7 KB  |  234 lines

  1. /*
  2.  * $Id: compression.c 44.1 1999/09/02 11:08:00 olsen Exp olsen $
  3.  *
  4.  * :ts=4
  5.  *
  6.  * COPYRIGHT:
  7.  *
  8.  *   Unless otherwise noted, all files are Copyright (c) 1999 Amiga, Inc.
  9.  *   All rights reserved.
  10.  *
  11.  * DISCLAIMER:
  12.  *
  13.  *   This software is provided "as is". No representations or warranties
  14.  *   are made with respect to the accuracy, reliability, performance,
  15.  *   currentness, or operation of this software, and all use is at your
  16.  *   own risk. Neither Amiga nor the authors assume any responsibility
  17.  *   or liability whatsoever with respect to your use of this software.
  18.  *
  19.  */
  20.  
  21. #include "global.h"
  22.  
  23. /*****************************************************************************/
  24.  
  25. LONG
  26. StripWhiteSpace(BYTE * source,LONG size)
  27. {
  28.     LONG i;
  29.  
  30.     /* Optimization: strip all trailing zero bytes. */
  31.     for(i = size ; i > 0 ; i--)
  32.     {
  33.         if(source[i-1] != 0)
  34.         {
  35.             size = i;
  36.             break;
  37.         }
  38.     }
  39.  
  40.     return(size);
  41. }
  42.  
  43. /*****************************************************************************/
  44.  
  45. /* PCL compression method #2, also known as "TIFF packbits" or ByteRun1. */
  46. LONG
  47. CompressMethod2(
  48.     UBYTE * src,
  49.     UBYTE * dest,
  50.     LONG count)
  51. {
  52.     UBYTE *    last = dest + count;
  53.  
  54.     UBYTE * outptr;
  55.     UBYTE * inptr;
  56.     UBYTE * saveptr;
  57.  
  58.     UBYTE    data;        /* data byte */
  59.     UBYTE    lastbyte;    /* last byte */
  60.     LONG    repcount;    /* repeat count */
  61.     LONG    litcount;    /* literal count */
  62.  
  63.     inptr = src;
  64.     outptr = dest;
  65.  
  66.     /* Start loop through data. Check for possible repeat at beginning. */
  67.     while(count > 0)
  68.     {
  69.         /* get value to work with */
  70.         data = (*inptr++);
  71.         count--;
  72.  
  73.         /* no repeat count yet */
  74.         repcount = 0;
  75.  
  76.         /* Check for repeat, since we are not in the middle
  77.          * of a literal run, it does not have to be more than
  78.          * two bytes of similar data.
  79.          */
  80.         while(count > 0 && (*inptr) == data)
  81.         {
  82.             repcount++;
  83.             inptr++;
  84.  
  85.             count--;
  86.         }
  87.  
  88.         /* Now, if we are out of data (count == 0), then
  89.          * if the repeated byte was zero, then ignore it
  90.          * completely (don't bother outputing the trailing zeros).
  91.          */
  92.         if(count == 0 && data == 0)
  93.             break; /* done */
  94.  
  95.         /* If there was a repeat (repcount > 0), then we
  96.          * can output the command here, otherwise, we
  97.          * need to go into literal run mode.
  98.          *
  99.          * Note:  This is a while loop because the repeat count
  100.          * may actually be greater than 127.
  101.          */
  102.  
  103.         if(repcount >= 1) /* repeat mode */
  104.         {
  105.             while(repcount > 127)
  106.             {
  107.                 if(outptr + 2 > last)
  108.                     return(-1);
  109.  
  110.                 (*outptr++) = 129;    /* count 127 */
  111.                 (*outptr++) = data;    /* value */
  112.                 repcount -= 128;    /* offset */
  113.             }
  114.  
  115.             if(repcount > 0)
  116.             {
  117.                 if(outptr + 2 > last)
  118.                     return(-1);
  119.  
  120.                 (*outptr++) = 256 - repcount;    /* count */
  121.                 (*outptr++) = data;        /* value */
  122.  
  123.                 /* Now pop to the top of the loop 
  124.                  * looking for more repeat counts.
  125.                  */
  126.  
  127.                 continue; /* top of loop */
  128.             }
  129.  
  130.             /* Special case.  If we have arrived at this point,
  131.              * then repcount is now equal to 0.  This means
  132.              * that when we entered this section, repcount
  133.              * was a multiple of 128 (i.e. 128 :-).
  134.              *
  135.              * This means that there were 129 identical bytes,
  136.              * so the output does a replicate of 127 which
  137.              * gives 128 bytes, and we now have one byte left
  138.              * over which should NOT be output as a repeat
  139.              * run, rather it should be merged into the following
  140.              * literal run (if it exists).
  141.              *
  142.              * So, we will simply fall thru to the next section
  143.              * of code which assumes that we are working on 
  144.              * a literal run.
  145.              */
  146.         }
  147.  
  148.         /* Literal run.  At this point, the current data byte
  149.          * does NOT match the following byte.  We will transfer
  150.          * these non-identical bytes until:
  151.          *
  152.          *      1)  we run out of input data (count == 0).
  153.          *      2)  we run out of room in this output block (128)
  154.          *      3)  we come across a value which occurs at least
  155.          *          three times in a row.  A value occuring only
  156.          *          twice in a row does NOT justify dropping
  157.          *          out of a literal run.
  158.          *
  159.          * Special case:  If we run out of room in the output block
  160.          * (which is 128 bytes), the last two values are the same,
  161.          * AND there is more input, it makes sense to restart
  162.          * the repeat detector in case the following bytes are
  163.          * repeats of the two.  A simple check of the following
  164.          * byte will determine this.
  165.          * (This case falls out with the test for triples below).
  166.          *
  167.          * Special case:  If we run out of room in the output block
  168.          * (which is 128 bytes), the last value is the same as
  169.          * the next one on the input, then it is better to let
  170.          * that byte be used in a possible replicate run following
  171.          * the literal run.  If the last byte matches ONLY the
  172.          * following byte, (and not the one after that, it is
  173.          * a wash, but for best results, we will test the
  174.          * following two bytes.
  175.          */
  176.  
  177.         litcount = 0;
  178.         saveptr = outptr++;    /* save location of the command byte */
  179.  
  180.         if(outptr + 1 > last)
  181.             return(-1);
  182.  
  183.         (*outptr++) = data;    /* save the first byte. */
  184.  
  185.         lastbyte = data;    /* remember for testing */
  186.  
  187.         while(count > 0 && litcount < 127)
  188.         {
  189.             data = (*inptr++);
  190.             count--;
  191.             litcount++;
  192.  
  193.             if(outptr + 1 > last)
  194.                 return(-1);
  195.  
  196.             (*outptr++) = data;
  197.  
  198.             /* Test to see if this byte matched the last one.
  199.              * If so, check the next one for a triple.
  200.              */
  201.             if(lastbyte == data && count > 0 && (*inptr) == data)
  202.             {
  203.                 /* We have a triple, adjust accordingly.
  204.                  * Add two bytes back onto the input.
  205.                  */
  206.  
  207.                 count += 2;
  208.                 inptr -= 2;
  209.                 outptr -= 2;
  210.                 litcount -= 2;
  211.  
  212.                 break; /* out of loop */
  213.             }
  214.  
  215.             lastbyte = data; /* save data byte */
  216.         }
  217.  
  218.         /* Check the special case number 2 above. */
  219.         if(litcount == 127 && count > 1 && data == (*inptr) && data == inptr[1])
  220.         {
  221.             /*  Restore the last byte to the input stream */
  222.             count += 1;
  223.             inptr -= 1;
  224.             outptr -= 1;
  225.             litcount -= 1;
  226.         }
  227.  
  228.         /* Save the literal run count. */
  229.         (*saveptr) = litcount;
  230.     }
  231.  
  232.     return(outptr - dest);
  233. }
  234.